package com.sduept.nwld.dataserver.manager.protection;

import com.sduept.bigdata.risk.service.RiskAlarmMessageQueryManager;
import com.sduept.cim.model.core.Substation;
import com.sduept.component.message.model.AlarmReceiveRole;
import com.sduept.core.dao.SuperDAO;
import com.sduept.message.entity.AlarmMessage;
import com.sduept.message.entity.AlarmMessageCheck;
import com.sduept.message.manager.MessageReceiveConfigManager;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.manager.message.MosMessagePushManager;
import com.sduept.nwld.dataserver.manager.message.interfaces.imp.MosMessageObserver;
import com.sduept.permission.entity.DepartmentEntityBean;
import com.sduept.permission.entity.PersonnelEntityBean;
import com.sduept.permission.entity.RoleEntityBean;
import com.sduept.permission.manager.DepartManager;
import com.sduept.permission.manager.PermissionManager;
import com.sduept.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class AlarmMessageReceiverManager {
	@Autowired
	private SuperDAO dao;
	@Autowired
	private AlarmReceiveRoleManager arm;
	@Autowired
	private DepartManager dm;
	@Autowired
	private PermissionManager permissionManager;
	@Autowired
	private RiskAlarmMessageQueryManager riskQueryM;
	@Autowired
	private CimManager cimM;
	@Autowired
	private MosMessagePushManager mosMessM;
	@Autowired
	private MessageReceiveConfigManager messageReceiveConfigManager;
	

	public List<Substation> findSubstation(String stationName, String subControlAreaId, String vol) {
		String sql = "";
		List<Object> params = new ArrayList<>();
		if(StringUtils.isNotEmpty(stationName)) {
			sql += " and name = ? ";
			params.add(stationName);
		} else {
			if(StringUtils.isNotEmpty(vol)) {
				sql += " and standVoltagelevel = ? ";
				params.add(Float.parseFloat(vol));
			}
			if(StringUtils.isNotEmpty(subControlAreaId)) {
				sql += " and subControlArea = ?";
				params.add(subControlAreaId);
			}
		}
		sql = sql.replaceFirst(" and", "");
		return dao.findByCondition(Substation.class, sql, params.toArray());
	}
	
	//TODO：注：以下紧邻的8个方法原在AlarmMessageCheckManager中，由于提出公用消息包中无core包依赖，所以暂时把这几个方法放到这。
	/**
	 * 获得消息发送者
	 * @return 
	 */
	public Map<String, PersonnelEntityBean> findAllMsgReceiver(String alarmType, String stationId) {
		if(StringUtils.isEmpty(alarmType) || StringUtils.isEmpty(stationId)) {
			return null;
		}
		List<String> roleIds = findAlarmTypeRoleIds(alarmType);
		Boolean flag = arm.ifAllReceive(alarmType);
//		List<String> deptIds = findAllDeptIds(stationId, flag);
		List<String> deptIds = findAllowDeptIds(stationId, flag);
		Map<String, PersonnelEntityBean> msgReceivers = findPersonByDeptsAndRoles(deptIds, roleIds);
		return msgReceivers;
	}
	/**
	 * 根据消息类型获取接收该消息的角色
	 * @param alarmType
	 * @return
	 */
	private List<String> findAlarmTypeRoleIds(String alarmType) {
		List<AlarmReceiveRole> alarmReceiveRoleList = arm.findByAlarmType(alarmType);
		List<String> roleIds = new ArrayList<String>();
		for (AlarmReceiveRole alarmReceiveRole : alarmReceiveRoleList) {
			if(StringUtils.isNotEmpty(alarmReceiveRole.getRoleId())) {
				roleIds.add(alarmReceiveRole.getRoleId());
			}
		}
		return roleIds;
	}
	/**
	 * flag == true,上级部门允许接收短信，根据组织机构，获取对变电站有查看权限的所有部门
	 * flag == false,上级部门不允许接收短信，根据组织机构，获取对变电站有查看权限的所有部门，然后找出该变电站的直接父部门
	 * @param stationId
	 * @param flag
	 * @return
	 */
	public List<String> findAllowDeptIds(String stationId, Boolean flag) {
		List<String> deptIds = permissionManager.findAllowOperatorsByResource(stationId);
		if(null != flag) {
			if(true == flag) {
				// flag==true,获取所有部门（根据组织机构，获取对变电站有查看权限的所有部门）
				return deptIds;
			} else {
				// flag==false,仅获取直属父部门
				return findDirectParentDeptIds(deptIds);
			}
		} else {
			return null;
		}
	}
	/**
	 * 根据部门的id集合List<String> deptIds获取最底层部门
	 * @param deptIds
	 */
	private List<String> findDirectParentDeptIds(List<String> deptIds) {
		List<String> results = new ArrayList<String>();
		results.addAll(deptIds);
//		for (String id : deptIds) {
//			results.add(id);
//		}
		DepartmentEntityBean dept = null;
		for (String id : deptIds) {
			dept = dm.findDepartmentById(id);
			if(null != dept) {
				DepartmentEntityBean pDept = dept.getParent();
				if(null != pDept) {
					results = recursiveFindSubDepartments(deptIds, pDept, results);
				}
			} else {
				// 该id对应的部门不存在（是人员的id），从result中移除该id
				results.remove(id);
			}
		}
		return results;
	}
	private List<String> recursiveFindSubDepartments(List<String> deptIds, DepartmentEntityBean dept, List<String> results) {
		if(deptIds.contains(dept.getId())) {
			results.remove(dept.getId());
			DepartmentEntityBean pDept = dept.getParent();
			if(null != pDept) {
				results = recursiveFindSubDepartments(deptIds, pDept, results);
			}
		}
		return results;
	}
	/**
	 * 获取指定部门下的指定角色的人员
	 * @param deptIds
	 * @param roleIds
	 * @return
	 */
	private Map<String, PersonnelEntityBean> findPersonByDeptsAndRoles(List<String> deptIds, List<String> roleIds) {
		if(null == deptIds || null == roleIds || deptIds.size() == 0 || roleIds.size() == 0) {
			return null;
		} else {
			Map<String,PersonnelEntityBean> personMap = new HashMap<String, PersonnelEntityBean>();
			for (String deptId : deptIds) {
				List<PersonnelEntityBean> persons = dm.findDeptPersonnels(deptId);
				for (PersonnelEntityBean p : persons) {
					if(!personMap.containsKey(p.getId())) {
						Set<RoleEntityBean> roles = p.getRoles();
						for (RoleEntityBean role : roles) {
							if(roleIds.contains(role.getId())) {
								personMap.put(p.getId(), p);
								break;
							}
						}
					}
				}
			}
			return personMap;
		}
	}
	/**
	 * 由异常消息内容获得异常厂站，根据厂站获得管理者，即为短信发送者
	 * @param alarmMessageCheck
	 */
	public void sendMessage(AlarmMessageCheck alarmMessageCheck) {
		Date msgTime = alarmMessageCheck.getMsgTime();
		String msgType = alarmMessageCheck.getMsgType();
		String time = DateUtil.getStringDate(msgTime, DateUtil.pattern_ymdhm);
		String mesgContent = time+"，"+alarmMessageCheck.getMsgContent()+"，请运维单位检查分析，并于3个工作日内登陆保护大数据系统填报检查情况";
		String stationName = getStationName(alarmMessageCheck);
		if(null != stationName) {
			List<Substation> stationList = cimM.getStationByName(stationName);
			if(stationList.size()>0) {
				Substation station = stationList.get(0);
				List<String> phoneList = new ArrayList<String>();
				Map<String, PersonnelEntityBean> msgReceivers = findAllMsgReceiver(alarmMessageCheck.getMsgType(), station.getId());
				for (PersonnelEntityBean per : msgReceivers.values()) {
					boolean flag = messageReceiveConfigManager.exist(per.getCode(), msgType, MosMessageObserver.MOS_RECEIVER_MESSAGE);
					if(flag) {
						if(StringUtils.isNotEmpty(per.getTelephone())) {
							phoneList.add(per.getTelephone());
						}
					}
				}
				try {
					mosMessM.sendMsgByMass(phoneList,alarmMessageCheck.getMsgType(),mesgContent);
				} catch (Exception e) {
					log.error("短信推送异常");
					e.printStackTrace();
				}
			}
		}
	}
	/**
	 * 根据异常消息获得发生异常的厂站
	 * @param alarmMessageCheck
	 * @return
	 */
	public String getStationName(AlarmMessageCheck alarmMessageCheck) {
		// 获取消息的stationName
		String stationName1 = null;
		if(null != alarmMessageCheck) {
			String msgId = alarmMessageCheck.getMsgId();
			if(StringUtils.isNotEmpty(msgId)) {
				AlarmMessage alarmM = riskQueryM.getAlarmMessageById(alarmMessageCheck.getMsgId());
				if(null != alarmM) {
					stationName1 = alarmM.getStationName();
				}
			}
		}
		if(StringUtils.isNotEmpty(stationName1)) {
			return stationName1;
		} else {
			// 通过消息内容获取变电站
			String stationName2 = null;
			String msgContent = alarmMessageCheck.getMsgContent();
			if(null != msgContent) {
				if(msgContent.contains("/")) {
					String[] contents = msgContent.split("/");
					stationName2 = contents[0];
				}
			}
			return stationName2;
		}
	}

}
